package rmi;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;

import log.Logger;

import philosoph.Philosoph;
import philosoph.StdPhilosoph;

public class RMIServerPhilosoph extends UnicastRemoteObject implements RMIServerPhilosophInterface {
	private static final long serialVersionUID = 3514239411309716898L;
	
	private ArrayList<Thread> threads;

	protected RMIServerPhilosoph() throws RemoteException {
		super();
		threads = new ArrayList<Thread>();
	}

	@Override
	public void createAndStart(final Logger logger, final String name, int thinkTime, int eatTime, final String hostMasterTable) throws RemoteException {
		final Philosoph phil = new StdPhilosoph(thinkTime, eatTime, name);
		
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					logger.log("Philosoph:\t " + name + " created. MasterTable: " + hostMasterTable);
					RMIServerTableInterface localTable = (RMIServerTableInterface) Naming.lookup("//localhost/Table");
					RMIServerTableMasterInterface masterTable = (RMIServerTableMasterInterface) Naming.lookup("//"+hostMasterTable+"/TableMaster") ;
					
					while (true) {
						logger.log("Philosoph:\t " + name + " starts thinking.");
						phil.think();
						logger.log("Philosoph:\t " + name + " stopped thinking. Is hungry now and looking for a seat!");
						if(localTable.sitNEat(phil)) {
							// try to find a seat on the localhost first, then other tables
							masterTable.wakeOthers();
						}
						else {
							// otherwise ask TableMaster to find a seat and eat.
							masterTable.sitNEat(phil);
						}
					}
				} catch (InterruptedException e) {
					// nothing
				} catch (RemoteException e) {
					// nothing
				} catch (MalformedURLException e) {
					// nothing
				} catch (NotBoundException e) {
					// nothing
				}
			}
		});
		threads.add(t);
		t.start();
	}

	@Override
	public void stopAll() throws RemoteException, InterruptedException {
		for (Thread t : threads) {
			t.interrupt();
		}
		for (Thread t : threads) {
			t.join(1000);
		}
	}

}
